import * as fs from 'fs'
import * as path from 'path'
import * as os from 'os'
import * as step from '@flow-step/step-toolkit'
import {PackInputs} from './pack-inputs'

export const SEP = path.sep
export const EOL = os.EOL

export function emptyDir(path: string) {
    const files = fs.readdirSync(path)
    files.forEach(file => {
        const filePath = `${path}/${file}`
        const stats = fs.statSync(filePath)
        if (stats.isDirectory()) {
            emptyDir(filePath)
        } else {
            fs.unlinkSync(filePath)
        }
    })
}

export function rmEmptyDir(path: string, level = 0) {
    const files = fs.readdirSync(path)
    if (files.length > 0) {
        let tempFile = 0
        files.forEach(file => {
            tempFile++
            rmEmptyDir(`${path}/${file}`, 1)
        })
        if (tempFile === files.length && level !== 0) {
            fs.rmdirSync(path)
        }
    } else {
        level !== 0 && fs.rmdirSync(path)
    }
}

/**
 * @param {*} path
 */
export function clearDir(path: string) {
    emptyDir(path)
    rmEmptyDir(path)
}


/**
 * Packages compressed into zip format by using 7z.exe under win32
 * @param packInputs 
 * @returns 
 */
export async function sevenZipPack(packInputs: PackInputs): Promise<number> {
    if (packInputs.filePath.indexOf(' ') != -1) {
        packInputs.includePathInArtifact = 'true'
        let args = [
            'a',
            '-ttar',
            packInputs.artifactFullName,
            ...packInputs.sourcePath
        ]
        step.info(`7z.exe ${args}`)
        return step.exec.call(packInputs.sevenZipLocation, args, {
            listener: {
                stdoutLine: (line: string) => {
                    step.info(line)
                },
                stderrLine: (line: string) => {
                    step.error(line)
                }
            }
        })
    } else {
        if (packInputs.includePathInArtifact === 'true') {
            step.info('Pack single file with file path')
            let args = [
                'a',
                '-ttar',
                packInputs.artifactFullName,
                ...packInputs.sourcePath
            ]
            step.info(`7z.exe ${args}`)
            return step.exec.call(packInputs.sevenZipLocation, args, {
                listener: {
                    stdoutLine: (line: string) => {
                        step.info(line)
                    },
                    stderrLine: (line: string) => {
                        step.error(line)
                    }
                }
            })
        } else {
            step.info('Pack single file without file path')
            let stat = fs.lstatSync(packInputs.sourcePath[0])
            if (stat.isFile()) {
                let args = [
                    'a',
                    '-ttar',
                    packInputs.artifactFullName,
                    `${packInputs.sourcePath[0]}`
                ]
                return step.exec.call(packInputs.sevenZipLocation, args, {
                    listener: {
                        stdoutLine: (line: string) => {
                            step.info(line)
                        },
                        stderrLine: (line: string) => {
                            step.error(line)
                        }
                    }
                })
            } else if (stat.isDirectory()) {
                let args = [
                    'a',
                    '-ttar',
                    packInputs.artifactFullName,
                    `${packInputs.sourcePath[0]}${SEP}*`
                ]
                return step.exec.call(packInputs.sevenZipLocation, args, {
                    listener: {
                        stdoutLine: (line: string) => {
                            step.info(line)
                        },
                        stderrLine: (line: string) => {
                            step.error(line)
                        }
                    }
                })
            } else {
                step.error(
                    `Could not find files / folders: ${packInputs.filePath}`
                )
                fs.readdirSync(packInputs.projectDir)
                throw new Error('Could not find files / folders')
            }
        }
    }
}

/**
 * Packages compressed into tgz format by using tar command under Linux
 * @param packInputs 
 * @returns 
 */
export async function tarPack(packInputs: PackInputs): Promise<number> {
    let options = ''
    if (packInputs.gitIgnore === 'true') {
        options = '--exclude=.git'
    }
    if (packInputs.filePath.indexOf(' ') != -1) {
        step.info(
            `tar ${options} -zcPf ${packInputs.artifactFullName} ${packInputs.sourcePath}`
        )
        packInputs.includePathInArtifact = 'true'
        return step.exec.call(
            'tar',
            [options, '-zcPf', packInputs.artifactFullName, ...packInputs.sourcePath],
            {
                listener: {
                    stdoutLine: (line: string) => {
                        step.info(line)
                    },
                    stderrLine: (line: string) => {
                        step.error(line)
                    }
                }
            }
        )
    } else {
        if (packInputs.includePathInArtifact === 'true') {
            step.info('Pack single file with file path')
            step.info(
                `tar ${options} -zcPf ${packInputs.artifactFullName} ${packInputs.sourcePath}`
            )
            return step.exec.call(
                'tar',
                [
                    options,
                    '-zcPf',
                    packInputs.artifactFullName,
                    ...packInputs.sourcePath
                ],
                {
                    listener: {
                        stdoutLine: (line: string) => {
                            step.info(line)
                        },
                        stderrLine: (line: string) => {
                            step.error(line)
                        }
                    }
                }
            )
        } else {
            step.info('Pack single file without file path')
            let stat = fs.lstatSync(packInputs.sourcePath[0])
            if (stat.isFile()) {
                let fileName = path.basename(packInputs.sourcePath[0])
                let dirName = path.dirname(packInputs.sourcePath[0])
                return step.exec.call(
                    'tar',
                    [
                        options,
                        '-zcPf',
                        packInputs.artifactFullName,
                        '-C',
                        dirName,
                        fileName
                    ],
                    {
                        listener: {
                            stdoutLine: (line: string) => {
                                step.info(line)
                            },
                            stderrLine: (line: string) => {
                                step.error(line)
                            }
                        }
                    }
                )
            } else if (stat.isDirectory()) {
                return step.exec.call(
                    'tar',
                    [
                        options,
                        '-zcPf',
                        packInputs.artifactFullName,
                        '-C',
                        ...packInputs.sourcePath,
                        '.'
                    ],
                    {
                        listener: {
                            stdoutLine: (line: string) => {
                                step.info(line)
                            },
                            stderrLine: (line: string) => {
                                step.error(line)
                            }
                        }
                    }
                )
            } else {
                step.error(
                    `Could not find files / folders: ${packInputs.filePath}`
                )
                fs.readdirSync(packInputs.projectDir)
                throw new Error('Could not find files / folders')
            }
        }
    }
}